﻿using Microsoft.Extensions.Logging;
using PHMEE.Admin;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace PHMEE.MqttClient
{
    public class ClientCenter
    {
        private readonly ILogger<ClientCenter> _logger;

        public ClientCenter(ILogger<ClientCenter> logger)
        {
            _logger = logger;
        }
        /// <summary>
        /// 缓存字段
        /// </summary>
        private ConcurrentDictionary<string, IServiceContainer> m_OrderTemporaryStorageArea = new ConcurrentDictionary<string, IServiceContainer>(StringComparer.OrdinalIgnoreCase);

        public PackageInfoDto<T, TDataType> AddPackToCache<T, TDataType>(BaseCommand command, T entity, string key = null) where T : PackBaseDto<TDataType>, new()
        {
            PackageInfoDto<T, TDataType> result = new PackageInfoDto<T, TDataType>();
            if (key == null)
                key = command.GetType().Name + command.SN + entity.Id;
            //获取缓存中的分包数据列表
            List<T>? cacheData = GetTemporaryObject<List<T>>(key);
            if (cacheData == null || cacheData == default)
            {
                cacheData = new List<T>();
            }
            result.Id = entity.Id;
            cacheData = cacheData.Where(p => p.Id == entity.Id && p.PackIndex != entity.PackIndex).ToList();
            if (entity.PackCount < entity.PackIndex)
            {
                result.ReciveCount = cacheData.Count(p => p.PackIndex > -1);
                return result;
            }
            // 添加当前分包到缓存数据列表
            cacheData.Add(entity);
            _logger.LogInformation($"添加分包数据到缓存: {key}, PackIndex: {entity.PackIndex}");
            result.ReciveCount = cacheData.Count(p => p.PackIndex > -1);

            // 检查是否已接收全部分包
            if (cacheData.Count(p => p.PackIndex > -1) == entity.PackCount)
            {
                //包接收完毕 开始拼包
                result.DataModel = Clone(entity);
                var AllLength = cacheData.Sum(p => p.Content.Length);
                result.DataModel.PackCount = cacheData.Count(p => p.PackIndex > -1);
                result.DataModel.Content = new TDataType[AllLength];
                cacheData = cacheData.OrderBy(p => p.PackIndex).ToList();
                var copyLength = 0;
                foreach (var copyData in cacheData)
                {
                    Array.Copy(copyData.Content, 0, result.DataModel.Content, copyLength, copyData.Content.Length);
                    copyLength += copyData.Content.Length;
                }
                result.IsComplete = true;

                // 更新缓存以反映最新的 cacheData
                //AddOrUpdateTemporaryObject<List<T>>(key, cacheData);

                //移除缓存中对应的分包数据
                if (m_OrderTemporaryStorageArea.TryRemove(key, out IServiceContainer sc))
                {
                    sc.RemoveService(typeof(List<T>));
                    _logger.LogInformation($"成功移除缓存: {key}");
                }
                else
                {
                    _logger.LogError($"移除缓存错误！当前移除的是【{key}】");
                }
                //返回拼包后的结果
                return result;
            }
            else
            {
                // 如果不是最后一个包，则更新缓存中的分包数据列表
                AddOrUpdateTemporaryObject<List<T>>(key, cacheData);
                _logger.LogInformation($"更新缓存中的分包数据: {key}, 目前收到的分包数量: {cacheData.Count}");
            }
            return result;
        }

        /// <summary>
        /// 添加缓存对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="instance"></param>
        public void AddOrUpdateTemporaryObject<T>(string key, object instance)
        {

            // 添加日志记录
            _logger.LogInformation($"正在添加或更新键：{key}");

            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("没有缓存对象 Key");

            m_OrderTemporaryStorageArea.AddOrUpdate(key, (newKey) =>
            {
                var serviceContainer = new ServiceContainer();
                serviceContainer.AddService(typeof(T), instance);
                return serviceContainer;
            }, (oldKey, oldValue) =>
            {
                oldValue.RemoveService(typeof(T));//移除旧的服务(如果存在)
                oldValue.AddService(typeof(T), instance);
                return oldValue;
            });
        }
        /// <summary>
        /// 根据Key获取缓存对象
        /// </summary>
        /// <typeparam name="T">缓存对象类型</typeparam>
        /// <param name="key">缓存对象的Key</param>
        /// <returns></returns>
        public T GetTemporaryObject<T>(string key)
        {
            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("没有缓存对象 Key");
            IServiceContainer sc;
            return m_OrderTemporaryStorageArea.TryGetValue(key, out sc) ? (T)sc.GetService(typeof(T)) : default;
        }

        public T? RemoveTemporaryObject<T>(string key)
        {

            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("没有缓存对象 Key");
            IServiceContainer sc;
            return m_OrderTemporaryStorageArea.TryRemove(key, out sc) ? (T)sc.GetService(typeof(T)) : default;
        }

        /// <summary>
        /// 对象克隆
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="RealObject"></param>
        /// <returns></returns>
        public static T? Clone<T>(T realObject)
        {
            var jsonString = JsonSerializer.Serialize(realObject);
            return JsonSerializer.Deserialize<T>(jsonString);
        }

    }
}
